package com.wxy.livebroadcast.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.wxy.livebroadcast.entity.*;
import com.wxy.livebroadcast.service.SocketService;
import com.wxy.livebroadcast.service.WebSocketServer;
import com.wxy.livebroadcast.utils.ComputerIdentifier;
import javafx.stage.Stage;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

@Controller
@CrossOrigin
@Slf4j
public class SystemController {

    @Resource
    private SocketService socketService;

    //页面请求
    @GetMapping("/socket/test")
    public String socket(Model model) {
        return "socket1";
    }

    @GetMapping("/socket/getSocketList")
    @ResponseBody
    public List<String> getSocketList(){
        List<String> list = new ArrayList<>();
        Set<WebSocketServer> set = WebSocketServer.getWebSocketSet();
        for (WebSocketServer server : set){
            if ("aW5kZXgNCg==".equals(server.name)){
                continue;
            }
            list.add(server.name);
        }
        return list;
    }

    @GetMapping("/socket/checkSocket")
    @ResponseBody
    public Result checkSocket(@RequestParam("name") String name){
        if (socketService.checkSocket(name)){
            return Result.ok();
        } else {
            return Result.failed();
        }
    }

    //推送数据接口
    @ResponseBody
    @RequestMapping("/socket/push")
    public Result pushToWeb(@RequestParam("name") String name, @RequestParam("content") String content, @RequestParam("role") Integer role, @RequestParam("username") String username) {
        try {
            MessageObj<PushObj> messageObj = new MessageObj<PushObj>();
            PushObj pushObj = new PushObj();
            pushObj.setContent(content);
            pushObj.setUsername(username);
            messageObj.setType(1);
            messageObj.setName(name);
            messageObj.setRole(role);
            messageObj.setData(pushObj);
            log.info("send messageObj = " + JSON.toJSONString(messageObj));
            WebSocketServer.sendInfo(JSON.toJSONString(messageObj), name);
        } catch (IOException e) {
            return Result.failed(e.getMessage());
        }
        return Result.ok();
    }

    //结束接口
    @ResponseBody
    @RequestMapping("/socket/end")
    public Result end(@RequestParam("name2") String name2) {
        try {
            MessageObj<EndObj> messageObj = new MessageObj<>();
            messageObj.setType(2);
            messageObj.setName(name2);
//            EndObj endObj = new EndObj();
//            endObj.setAsynCoin(asynCoin);
//            endObj.setNumber(number2);
//            endObj.setLike(like);
//            endObj.setFans(fans);
//            messageObj.setData(endObj);
            log.info("send endObj = " + JSON.toJSONString(messageObj));
            WebSocketServer.sendInfo(JSON.toJSONString(messageObj), name2);
        } catch (IOException e) {
            return Result.failed(e.getMessage());
        }
        return Result.ok();
    }

    // 人数接口
    @ResponseBody
    @RequestMapping("/socket/member")
    public Result member(@RequestParam("name3") String name3, @RequestParam("number") Integer number) {
        try {
            MemberObj memberObj  = new MemberObj();
            memberObj.setNumber(number);
            MessageObj<MemberObj> messageObj = new MessageObj<>();
            messageObj.setType(3);
            messageObj.setName(name3);
            messageObj.setData(memberObj);
            log.info("send endObj = " + JSON.toJSONString(messageObj));
            WebSocketServer.sendInfo(JSON.toJSONString(messageObj), name3);
        } catch (IOException e) {
            return Result.failed(e.getMessage());
        }
        return Result.ok();
    }

    // 超管警告接口
    @ResponseBody
    @RequestMapping("/socket/sendWarning")
    public Result sendWarning(@RequestParam("name9") String name9) {
        try {
            MessageObj<MemberObj> messageObj = new MessageObj<>();
            messageObj.setType(8);
            messageObj.setName(name9);
            log.info("sendWarning = " + JSON.toJSONString(messageObj));
            WebSocketServer.sendInfo(JSON.toJSONString(messageObj), name9);
        } catch (IOException e) {
            return Result.failed(e.getMessage());
        }
        return Result.ok();
    }

    @SneakyThrows
    private StageObj getStageObj(){
        byte[] bytes = new byte[2048];
        String projectPath = System.getProperty("user.dir");
        log.info("projectPath:{}", projectPath);

        String filePath = projectPath + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "stageMessage.txt";
        File file = FileUtil.file(filePath);
        if (!file.exists()){
            file.createNewFile();
        }
        BufferedInputStream inputStream = FileUtil.getInputStream(file);
        StringBuilder sb = new StringBuilder();
        int len = 0;
        while((len=inputStream.read(bytes)) != -1){
            sb.append(new String(bytes, 0, len));
        }
        String json = sb.toString();
        StageObj stageObj = JSON.parseObject(json, StageObj.class);
        inputStream.close();
        return stageObj;
    }

    @SneakyThrows
    private void putStageMessage(StageObj stageObj){
        String projectPath = System.getProperty("user.dir");
        log.info("projectPath:{}", projectPath);

        String filePath = projectPath + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "stageMessage.txt";
        File file = FileUtil.file(filePath);
        if (!file.exists()){
            file.createNewFile();
        }
        String json = JSON.toJSONString(stageObj);
        byte[] b = json.getBytes();
        BufferedOutputStream outputStream = FileUtil.getOutputStream(file);
        outputStream.write(b);
        outputStream.flush();
        outputStream.close();
    }

    // 发送阶段消息
    @ResponseBody
    @PostMapping("/socket/sendStage")
    public Result sendStage(@RequestParam("name5") String name5, @RequestParam("stage") Integer stage, @RequestParam("contents") List<String> contents) {
        // 发送消息
        sendStageMessage(stage, contents, name5);
        return Result.ok();
    }

    @ResponseBody
    @PostMapping("/socket/saveData")
    public Result saveData(@RequestParam("name5") String name5, @RequestParam("stage") Integer stage, @RequestParam("contents") List<String> contents) {
        StageObj stageObj = getStageObj();
        switch (stage){
            case 1:
                if (stageObj == null){
                    stageObj = new StageObj();
                    stageObj.setOneStage(contents);
                } else {
                    if (!CollectionUtil.isEmpty(stageObj.getOneStage())){
                        stageObj.getOneStage().clear();
                    }
                    stageObj.setOneStage(contents);
                }
                break;
            case 2:
                if (stageObj == null){
                    stageObj = new StageObj();
                    stageObj.setTwoStage(contents);
                } else {
                    if (!CollectionUtil.isEmpty(stageObj.getTwoStage())){
                        stageObj.getTwoStage().clear();
                    }
                    stageObj.setTwoStage(contents);
                }
                break;
            case 3:
                if (stageObj == null){
                    stageObj = new StageObj();
                    stageObj.setThreeStage(contents);
                } else {
                    if (!CollectionUtil.isEmpty(stageObj.getThreeStage())){
                        stageObj.getThreeStage().clear();
                    }
                    stageObj.setThreeStage(contents);
                }
                break;
            case 4:
                if (stageObj == null){
                    stageObj = new StageObj();
                    stageObj.setFourStage(contents);
                } else {
                    if (!CollectionUtil.isEmpty(stageObj.getFourStage())){
                        stageObj.getFourStage().clear();
                    }
                    stageObj.setFourStage(contents);
                }
                break;
            case 5:
                if (stageObj == null){
                    stageObj = new StageObj();
                    stageObj.setFiveStage(contents);
                } else {
                    if (!CollectionUtil.isEmpty(stageObj.getFiveStage())){
                        stageObj.getFiveStage().clear();
                    }
                    stageObj.setFiveStage(contents);
                }
                break;
            case 6:
                if (stageObj == null){
                    stageObj = new StageObj();
                    stageObj.setSixStage(contents);
                } else {
                    if (!CollectionUtil.isEmpty(stageObj.getSixStage())){
                        stageObj.getSixStage().clear();
                    }
                    stageObj.setSixStage(contents);
                }
                break;
            case 7:
                if (stageObj == null){
                    stageObj = new StageObj();
                    stageObj.setSevenStage(contents);
                } else {
                    if (!CollectionUtil.isEmpty(stageObj.getSevenStage())){
                        stageObj.getSevenStage().clear();
                    }
                    stageObj.setSevenStage(contents);
                }
                break;
            default:
                break;
        }
        // 存文件
        putStageMessage(stageObj);
        return Result.ok();
    }

    /**
     * 根据阶段获取消息
     * @param stage
     * @return
     */
    @ResponseBody
    @GetMapping("/getStages")
    public List<String> getStage(@RequestParam("stage") Integer stage) {
        StageObj stageObj = getStageObj();
        List<String> contents = null;
        if (stageObj == null){
            contents = new ArrayList<>();
            return contents;
        }
        switch (stage){
            case 1:
                contents = stageObj.getOneStage();
                break;
            case 2:
                contents = stageObj.getTwoStage();
                break;
            case 3:
                contents = stageObj.getThreeStage();
                break;
            case 4:
                contents = stageObj.getFourStage();
                break;
            case 5:
                contents = stageObj.getFiveStage();
                break;
            case 6:
                contents = stageObj.getSixStage();
                break;
            case 7:
                contents = stageObj.getSevenStage();
                break;
            default:
                break;
        }
        if (contents == null){
            contents = new ArrayList<>();
        }
        return contents;
    }

    @SneakyThrows
    private void sendStageMessage(Integer stage, List<String> contents, String name5) {
        StageMessage stageMessage = new StageMessage();
        stageMessage.setStage(stage);
        stageMessage.setContents(contents);
        MessageObj<StageMessage> messageObj = new MessageObj<>();
        messageObj.setType(6);
        messageObj.setName(name5);
        messageObj.setData(stageMessage);
        log.info("send stageObj = " + JSON.toJSONString(messageObj));
        WebSocketServer.sendInfo(JSON.toJSONString(messageObj), name5);
    }

    // 发送礼物消息
    @ResponseBody
    @RequestMapping("/socket/sendGift")
    public Result sendGift(@RequestParam("name6") String name6, @RequestParam("gift") Integer gift, @RequestParam("number") Integer number, @RequestParam("username") String username) {
        try {
            GiftObj giftObj  = new GiftObj();
            giftObj.setGift(gift);
            giftObj.setNumber(number);
            giftObj.setUsername(username);
            MessageObj<GiftObj> messageObj = new MessageObj<>();
            messageObj.setType(5);
            messageObj.setName(name6);
            messageObj.setData(giftObj);
            log.info("send giftObj = " + JSON.toJSONString(messageObj));
            WebSocketServer.sendInfo(JSON.toJSONString(messageObj), name6);
        } catch (IOException e) {
            return Result.failed(e.getMessage());
        }
        return Result.ok();
    }

    // 发送连麦消息
    @ResponseBody
    @RequestMapping("/socket/sendConnect")
    public Result sendConnect(@RequestParam("name7") String name7, @RequestParam("name8") String name8) {
        try {
            String roomId = new Random().nextInt(999999) + "";
            PcConnectObj pcConnectObj  = new PcConnectObj();
            pcConnectObj.setToName(name7);
            pcConnectObj.setRoomId(roomId);
            MessageObj<PcConnectObj> messageObj = new MessageObj<>();
            messageObj.setType(7);
            messageObj.setName(name8);
            messageObj.setData(pcConnectObj);
            log.info("send giftObj = " + JSON.toJSONString(messageObj));
            WebSocketServer.sendInfo(JSON.toJSONString(messageObj), name8);

            PcConnectObj pcConnectObj2  = new PcConnectObj();
            pcConnectObj2.setToName(name8);
            pcConnectObj2.setRoomId(roomId);
            MessageObj<PcConnectObj> messageObj2 = new MessageObj<>();
            messageObj2.setType(7);
            messageObj2.setName(name7);
            messageObj2.setData(pcConnectObj2);
            log.info("send giftObj = " + JSON.toJSONString(messageObj2));
            WebSocketServer.sendInfo(JSON.toJSONString(messageObj2), name7);
        } catch (IOException e) {
            return Result.failed(e.getMessage());
        }
        return Result.ok();
    }

    @SneakyThrows
    @GetMapping
    @RequestMapping("/")
    public String index(Model model){

        // 校验权限
        // 获取项目绝对路径
        byte[] buffer = new byte[2048];
        String property = System.getProperty("user.dir");
        File file = FileUtil.file(property + "\\code.txt");
        if (FileUtil.exist(file)){
            // 取值
            int bytesRead = 0;
            BufferedInputStream inputStream = FileUtil.getInputStream(file);
            bytesRead = inputStream.read(buffer);
            inputStream.close();
            if (bytesRead == -1){
                // 重新填写授权码，跳转授权页面
                return "code";
            } else {
                //将读取的字节转为字符串对象
                String code = new String(buffer, 0, bytesRead);
                // 调BOOM API 查看授权码是否被禁用
                // 校验,调BOOM API 查看授权码是否被禁用
                //链式构建请求
                String json = "{\"code\": \"" + code + "\"}";
                String param = URLEncoder.encode(json, "UTF-8");
                String result2 = HttpRequest.get("https://api2.bmob.cn/1/classes/code?where=" + param)
                        .header("X-Bmob-Application-Id", "838b808977bba318880cce79834d5240")
                        .header("X-Bmob-REST-API-Key", "d97afec083f53823a53b01b313d2ef4f")
                        .timeout(20000)
                        .execute().body();
                BmobResult bmobResult = JSON.parseObject(result2, BmobResult.class);
                if (CollectionUtil.isEmpty(bmobResult.getResults())){
                    return "code";
                } else {
                    Code codeObj = bmobResult.getResults().get(0);
                    if (!codeObj.isActive()){
                        return "code";
                    } else {
                        // 获取电脑的唯一标识
                        String licenseKey = ComputerIdentifier.generateLicenseKey();
                        log.info("licenseKey = " + licenseKey);
                        String computerId = codeObj.getComputerId();
                        if (StrUtil.isNotBlank(computerId) && !licenseKey.equals(computerId)){
                            return "code";
                        }
                    }
                }
            }
        } else {
            return "code";
        }

        List<String> list = new ArrayList<>();
        Set<WebSocketServer> set = WebSocketServer.getWebSocketSet();
        for (WebSocketServer server : set){
            list.add(server.name);
        }
        model.addAttribute("names", list);
        return "index";
    }

    //页面请求
    @SneakyThrows
    @ResponseBody
    @GetMapping("/active")
    public String active(@RequestParam("code") String code) {

        // 校验,调BOOM API 查看授权码是否被禁用
        //链式构建请求
        String json = "{\"code\": \"" + code + "\"}";
        String param = URLEncoder.encode(json, "UTF-8");
        String result2 = HttpRequest.get("https://api2.bmob.cn/1/classes/code?where=" + param)
        .header("X-Bmob-Application-Id", "838b808977bba318880cce79834d5240")
        .header("X-Bmob-REST-API-Key", "d97afec083f53823a53b01b313d2ef4f")
        .timeout(20000)
        .execute().body();
        BmobResult bmobResult = JSON.parseObject(result2, BmobResult.class);
        if (CollectionUtil.isEmpty(bmobResult.getResults())){
            return "授权码不存在!请重填!";
        } else {
            Code codeObj = bmobResult.getResults().get(0);
            if (!codeObj.isActive()){
                return "授权码被禁用!请找管理员!";
            } else {
                // 获取电脑的唯一标识
                String licenseKey = ComputerIdentifier.generateLicenseKey();
                log.info("licenseKey = " + licenseKey);
                String computerId = codeObj.getComputerId();
                if (StrUtil.isNotBlank(computerId) && !licenseKey.equals(computerId)){
                    return "授权码已被使用!请找管理员!";
                }

                // 绑定电脑
                String json2 = "{\"computerId\": \"" + licenseKey + "\"}";
                String result = HttpRequest.put("https://api2.bmob.cn/1/classes/code/" + codeObj.getObjectId())
                    .header("X-Bmob-Application-Id", "838b808977bba318880cce79834d5240")
                    .header("X-Bmob-REST-API-Key", "d97afec083f53823a53b01b313d2ef4f")
                    .header("Content-Type", "application/json").body(json2)
                    .timeout(20000)
                    .execute().body();
                log.info(result);
            }
        }

        // 存值
        String property = System.getProperty("user.dir");
        File file = FileUtil.file(property + "\\code.txt");
        if (FileUtil.exist(file)){
            FileUtil.del(file);
        }
        BufferedOutputStream outputStream = FileUtil.getOutputStream(file);
        byte[] b = code.getBytes();
        outputStream.write(b);
        outputStream.close();
        return "success";
    }

    @GetMapping({"/socket/getMsgList"})
    @ResponseBody
    public List<JsonObj> getMsgList()
    {
        return WebSocketServer.getMsgList();
    }

    @ResponseBody
    @PostMapping({"/uploadImg"})
    public Result uploadPicture(@RequestParam("file") MultipartFile file, HttpServletRequest request)
    {
        Map<String, Object> map = new HashMap();
        File targetFile = null;

        String url = "";
        int code = 1;
        System.out.println(file);

        String fileName = file.getOriginalFilename();
        if ((fileName != null) && (fileName != ""))
        {
            String returnUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/upload/imgs/";

            String path = request.getSession().getServletContext().getRealPath("") + "upload" + File.separator + "imgs";

            String fileSuffix = fileName.substring(fileName.lastIndexOf("."), fileName.length());

            fileName = System.currentTimeMillis() + "_" + new Random().nextInt(1000) + fileSuffix;

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            String fileAdd = sdf.format(new Date());

            path = path + File.separator + fileAdd + File.separator;
            log.info("path:{}", path);
            File file1 = new File(path);
            if ((!file1.exists()) && (!file1.isDirectory())) {
                file1.mkdirs();
            }
            targetFile = new File(file1, fileName);
            try
            {
                file.transferTo(targetFile);
                String projectPath = System.getProperty("user.dir");
                log.info("projectPath:{}", projectPath);

                String src = path + fileName;

                String destDir = projectPath + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "static" + File.separator + "upload" + File.separator + "imgs" + File.separator + fileAdd + File.separator;
                copyFile(src, destDir, fileName);

                url = returnUrl + fileAdd + "/" + fileName;
                return Result.ok(url);
            }
            catch (Exception e)
            {
                log.error("exception:", e);
                return Result.failed("上传失败");
            }
        }
        return Result.failed("文件名不能为空！");
    }

    public void copyFile(String src, String destDir, String fileName)
            throws IOException
    {
        FileInputStream in = new FileInputStream(src);
        File fileDir = new File(destDir);
        if (!fileDir.isDirectory()) {
            fileDir.mkdirs();
        }
        File file = new File(fileDir, fileName);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream out = new FileOutputStream(file);

        byte[] buffer = new byte[1024];
        int c;
        while ((c = in.read(buffer)) != -1) {
            for (int i = 0; i < c; i++) {
                out.write(buffer[i]);
            }
        }
        in.close();
        out.close();
    }

    @GetMapping({"/socket/getUserList"})
    @ResponseBody
    public Result getUserList(@RequestParam("name") String name)
    {
        List<UserEntity> list = new ArrayList();
        if ((name != null) && (!"".equals(name)))
        {
            CopyOnWriteArraySet<WebSocketServer> webSocketSet = WebSocketServer.getWebSocketSet();
            for (WebSocketServer server : webSocketSet) {
                if ((!"aW5kZXgNCg==".equals(server.name)) && (!name.equals(server.name)))
                {
                    UserEntity userEntity = new UserEntity();
                    userEntity.setName(server.name);
                    userEntity.setUrl(server.url);
                    list.add(userEntity);
                }
            }
        }
        return Result.ok(list);
    }

    @GetMapping({"/socket/connectUser"})
    @ResponseBody
    public Result connectUser(@RequestParam("current") String current, @RequestParam("toName") String toName, @RequestParam("room") String room)
    {
        if ((StrUtil.isEmpty(current)) || (StrUtil.isEmpty(toName))) {
            return Result.failed("用户名不能为空!");
        }
        Map<String, UserEntity> map = new HashMap();
        map.put("current", WebSocketServer.getUser(current));
        map.put("toName", WebSocketServer.getUser(toName));
        try
        {
            MessageObj<ConnectObj> messageObj = new MessageObj();
            messageObj.setType(Integer.valueOf(4));
            ConnectObj connectObj = new ConnectObj();
            connectObj.setCurrent(WebSocketServer.getUser(current));
            connectObj.setToName(WebSocketServer.getUser(toName));
            connectObj.setRoom(room);
            messageObj.setData(connectObj);
            log.info("send connectObj = " + JSON.toJSONString(messageObj));
            WebSocketServer.sendInfo(JSON.toJSONString(messageObj), toName);
        }
        catch (IOException e)
        {
            return Result.failed(e.getMessage());
        }
        return Result.ok();
    }
}
